
<template>
    <div class="video-container">
        <div
            class="__cov-video-container"
            @mouseenter="mouseEnterVideo"
            @mouseleave="mouseLeaveVideo"
        >
            <video
                :class="{ 'hide-cursor': !state.contrlShow }"
                class="__cov-video"
                :poster="options.poster"
            >
                <source
                    v-for="(source, index) in sources"
                    :src="source.src"
                    :type="source.type"
                    :key="index"
                />
            </video>
            <div class="__cov-contrl-content" transition="fade" v-show="state.contrlShow">
                <button class="__cov-contrl-play-btn" @click="play">
                    <svg
                        class="__cov-contrl-play-btn-icon"
                        v-show="!state.playing"
                        viewBox="0 0 47 57"
                        version="1.1"
                        xmlns="http://www.w3.org/2000/svg"
                    >
                        <!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
                        <title>播放</title>
                        <desc>Created with Sketch.</desc>
                        <defs />
                        <g
                            id="Page-1"
                            stroke="none"
                            stroke-width="1"
                            fill="none"
                            fill-rule="evenodd"
                        >
                            <polygon
                                id="Triangle-1"
                                stroke="#FFFFFF"
                                fill="#FFFFFF"
                                points="1 56 1 1 47 28.5"
                            />
                        </g>
                    </svg>
                    <svg
                        class="__cov-contrl-play-btn-icon"
                        v-show="state.playing"
                        viewBox="0 0 15 22"
                        version="1.1"
                        xmlns="http://www.w3.org/2000/svg"
                    >
                        <!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
                        <title>暂停</title>
                        <desc>Created with Sketch.</desc>
                        <defs>
                            <path
                                d="M0,0.979149244 L5,0.979149244 L5,22 L0,22 L0,0.979149244 Z M10,0.979149244 L15,0.979149244 L15,22 L10,22 L10,0.979149244 Z"
                                id="path-1"
                            />
                            <mask
                                id="mask-2"
                                maskContentUnits="userSpaceOnUse"
                                maskUnits="objectBoundingBox"
                                x="0"
                                y="0"
                                width="15"
                                height="21.0208508"
                                fill="white"
                            >
                                <use xlink:href="#path-1" />
                            </mask>
                        </defs>
                        <g
                            id="Page-1"
                            stroke="none"
                            stroke-width="1"
                            fill="none"
                            fill-rule="evenodd"
                        >
                            <use
                                id="Combined-Shape"
                                stroke="#FFFFFF"
                                mask="url(#mask-2)"
                                stroke-width="2"
                                fill="#FFFFFF"
                                xlink:href="#path-1"
                            />
                        </g>
                    </svg>
                </button>
                <div class="__cov-contrl-video-slider" @click="slideClick" @mousedown="videoMove">
                    <div
                        class="__cov-contrl-video-inner"
                        :style="{ 'transform': `translate3d(${video.pos.current}px, 0, 0)`}"
                    ></div>
                    <div class="__cov-contrl-video-rail">
                        <div
                            class="__cov-contrl-video-rail-inner"
                            :style="{ 'transform': 'translate3d(' +video.loaded + '%, 0, 0)'}"
                        ></div>
                    </div>
                </div>
                <div class="__cov-contrl-video-time">
                    <span class="__cov-contrl-video-time-text">{{video.displayTime}}</span>
                </div>
                <div class="__cov-contrl-vol-box">
                    <button class="__cov-contrl-play-btn" @click="volMuted">
                        <svg
                            class="__cov-contrl-vol-btn-icon"
                            viewBox="0 0 41 44"
                            version="1.1"
                            xmlns="http://www.w3.org/2000/svg"
                            xmlns:xlink="http://www.w3.org/1999/xlink"
                        >
                            <!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
                            <title>vol</title>
                            <desc>Created with Sketch.</desc>
                            <defs>
                                <path
                                    d="M8.61522369,12 L20,0.615223689 L20,37.3847763 L8.61522369,26 L1.99201702,26 C0.891856397,26 0,25.1029399 0,23.9941413 L0,14.0058587 C0,12.8980535 0.900176167,12 1.99201702,12 L8.61522369,12 L8.61522369,12 Z"
                                    id="cov-vol"
                                />
                            </defs>
                            <g
                                id="Page-1"
                                stroke="none"
                                stroke-width="2"
                                fill="none"
                                fill-rule="evenodd"
                            >
                                <g id="vol" transform="translate(2.000000, 3.000000)">
                                    <g id="cov-vol-icon">
                                        <g id="Combined-Shape-Clipped">
                                            <path
                                                v-show="volume.percent > 1 && !volume.muted"
                                                d="M25,29.5538997 C28.4589093,27.6757536 31.2629093,23.2984641 31.2629093,19.7769499 C31.2629093,16.2554357 28.4589093,11.8781461 25,10"
                                                id="vol-range-2"
                                                stroke="#FFFFFF"
                                            />
                                            <path
                                                v-show="volume.percent > 70 && !volume.muted"
                                                d="M28,35.5538997 C33.5816016,32.5231573 38.1063837,25.4595762 38.1063837,19.7769499 C38.1063837,14.0943235 33.5816016,7.03074247 28,4"
                                                id="vol-range-2"
                                                stroke="#FFFFFF"
                                            />
                                            <mask id="mask-2" fill="white">
                                                <use xlink:href="#cov-vol" />
                                            </mask>
                                            <use
                                                id="vol-path"
                                                stroke="#FFFFFF"
                                                stroke-width="3"
                                                xlink:href="#cov-vol"
                                            />
                                            <g
                                                id="Combined-Shape"
                                                mask="url(#mask-2)"
                                                stroke="#FFFFFF"
                                                stroke-width="2"
                                                fill="#FFFFFF"
                                            >
                                                <path
                                                    d="M8.61522369,12 L20,0.615223689 L20,37.3847763 L8.61522369,26 L1.99201702,26 C0.891856397,26 0,25.1029399 0,23.9941413 L0,14.0058587 C0,12.8980535 0.900176167,12 1.99201702,12 L8.61522369,12 L8.61522369,12 Z"
                                                    id="cov-vol"
                                                />
                                            </g>
                                        </g>
                                    </g>
                                </g>
                            </g>
                        </svg>
                    </button>
                    <div
                        class="__cov-contrl-vol-slider"
                        @click="volSlideClick"
                        @mousedown="volMove"
                    >
                        <div
                            class="__cov-contrl-vol-inner"
                            :style="{ 'transform': `translate3d(${volume.pos.current}px, 0, 0)`}"
                        ></div>
                        <div class="__cov-contrl-vol-rail"></div>
                    </div>
                </div>
                <button class="__cov-contrl-play-btn" @click="fullScreen">
                    <svg
                        class="__cov-contrl-vol-btn-icon"
                        viewBox="0 0 33 33"
                        version="1.1"
                        xmlns="http://www.w3.org/2000/svg"
                        xmlns:xlink="http://www.w3.org/1999/xlink"
                    >
                        <!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
                        <defs />
                        <g
                            id="Page-1"
                            stroke="none"
                            stroke-width="1"
                            fill="none"
                            fill-rule="evenodd"
                        >
                            <path
                                d="M31.1682064,22 L31.1682064,31.0073537 L22,31.0073537 M22,1 L31.0073537,1 L31.0073537,10.1682064 M1,10.0073537 L1,1 L10.1682064,1 M10.0073537,31.1682064 L1,31.1682064 L1,22"
                                id="Combined-Shape"
                                stroke="#FFFFFF"
                                stroke-width="2"
                            />
                        </g>
                    </svg>
                </button>
            </div>
        </div>
    </div>
</template>
<script>
import { onEvent, offEvent } from "@/utils";

const getMousePosition = function (e, type = "x") {
    if (type === "x") {
        return e.pageX;
    }
    return e.pageY;
};
const pad = (val) => {
    val = Math.floor(val);
    if (val < 10) {
        return "0" + val;
    }
    return val + "";
};
const timeParse = (sec) => {
    let min = 0;
    min = Math.floor(sec / 60);
    sec = sec - min * 60;
    return pad(min) + ":" + pad(sec);
};
export default {
    props: {
        url: {
            type: String,
            required: true,
        },
        sourcesType: {
            type: String,
            default: "mp4",
        },
    },
    data() {
        return {
            $video: null,
            sources: [
                {
                    src: this.url,
                    type: `video/${this.sourcesType}`,
                },
            ],
            options: {
                autoplay: false,
                volume: 0.6,
                poster: "",
            },
            video: {
                $videoSlider: null,
                len: 0,
                current: 0,
                loaded: 0,
                moving: false,
                displayTime: "00:00",
                pos: {
                    start: 0,
                    width: 0,
                    innerWidth: 0,
                    current: 0,
                },
            },
            volume: {
                $volBox: null,
                muted: false,
                percent: 60,
                moving: false,
                pos: {
                    start: 0,
                    width: 0,
                    innerWidth: 0,
                    current: 0,
                },
            },
            player: {
                $player: null,
                pos: null,
            },
            tmp: {
                contrlHideTimer: null,
            },
            state: {
                contrlShow: true,
                vol: 0.5,
                currentTime: 0,
                fullScreen: false,
                playing: false,
            },
        };
    },
    mounted() {
        this.init();
    },
    beforeDestroy() {
        offEvent(document, "mousemove", this.mouseMoveAction);
        offEvent(document, "mouseup", this.mouseUpAction);
    },
    methods: {
        init() {
            this.$video = this.$el.getElementsByTagName("video")[0];
            this.initCore();
            if (this.options.autoplay) {
                this.play();
            }
            onEvent(document, "mousemove", this.mouseMoveAction);
            onEvent(document, "mouseup", this.mouseUpAction);
        },
        initCore() {
            this.initVol();
            this.initVideo();
            this.initPlayer();
            const vol = this.options.volume || 0.9;
            this.setVol(vol);
        },
        initPlayer() {
            const $player = this.$el.getElementsByClassName(
                "__cov-video-container"
            )[0];
            this.player.pos = $player.getBoundingClientRect();
            this.player.$player = $player;
        },
        initVol() {
            const $volBox = this.$el.getElementsByClassName(
                "__cov-contrl-vol-slider"
            )[0];
            const $volInner = $volBox.getElementsByClassName(
                "__cov-contrl-vol-inner"
            )[0];
            this.volume.$volBox = $volBox;
            this.volume.pos.innerWidth = $volInner.getBoundingClientRect().width;
            this.volume.pos.start = $volBox.getBoundingClientRect().left;
            this.volume.pos.width =
                $volBox.getBoundingClientRect().width -
                this.volume.pos.innerWidth;
        },
        initVideo() {
            const $videoSlider = this.$el.getElementsByClassName(
                "__cov-contrl-video-slider"
            )[0];
            const $videoInner = $videoSlider.getElementsByClassName(
                "__cov-contrl-video-inner"
            )[0];
            this.$videoSlider = $videoSlider;
            this.video.pos.start = $videoSlider.getBoundingClientRect().left;
            this.video.pos.innerWidth = $videoInner.getBoundingClientRect().width;
            this.video.pos.width =
                $videoSlider.getBoundingClientRect().width -
                this.video.pos.innerWidth;
            this.getTime();
        },
        mouseEnterVideo() {
            if (this.tmp.contrlHideTimer) {
                clearTimeout(this.tmp.contrlHideTimer);
                this.tmp.contrlHideTimer = null;
            }
            this.state.contrlShow = true;
        },
        mouseLeaveVideo() {
            if (this.tmp.contrlHideTimer) {
                clearTimeout(this.tmp.contrlHideTimer);
            }
            this.tmp.contrlHideTimer = setTimeout(() => {
                this.state.contrlShow = false;
                this.tmp.contrlHideTimer = null;
            }, 2000);
        },
        toggleContrlShow() {
            this.state.contrlShow = !this.state.contrlShow;
        },
        getTime() {
            this.$video.addEventListener("durationchange", () => {});
            this.$video.addEventListener("progress", () => {
                // this.video.loaded = (-1 + (this.$video.buffered.end(0) / this.$video.duration)) * 100
            });
            this.video.len = this.$video.duration;
        },
        setVideoByTime(percent) {
            this.$video.currentTime = Math.floor(percent * this.video.len);
        },
        play() {
            this.state.playing = !this.state.playing;
            if (this.$video) {
                if (this.state.playing) {
                    this.$video.play();
                    this.mouseLeaveVideo();
                    this.$video.addEventListener("timeupdate", this.timeline);
                    this.$video.addEventListener("ended", () => {
                        this.state.playing = false;
                        this.video.pos.current = 0;
                        this.$video.currentTime = 0;
                    });
                } else {
                    this.$video.pause();
                }
            }
        },
        timeline() {
            const percent = this.$video.currentTime / this.$video.duration;
            this.video.pos.current = (this.video.pos.width * percent).toFixed(
                3
            );
            this.video.displayTime = timeParse(
                this.$video.duration - this.$video.currentTime
            );
        },
        volMove() {
            this.initVol();
            this.volume.moving = true;
        },
        videoMove() {
            this.initVideo();
            this.video.moving = true;
        },
        slideClick(e) {
            this.videoSlideMove(e);
        },
        volSlideClick(e) {
            this.volSlideMove(e);
        },
        volMuted() {
            this.$video.muted = !this.$video.muted;
            this.volume.muted = this.$video.muted;
        },
        setVol(val) {
            if (this.$video) {
                this.volume.pos.current = val * this.volume.pos.width;
                this.volume.percent = val * 100;
                this.$video.volume = val;
            }
        },
        fullScreen() {
            if (!this.state.fullScreen) {
                this.state.fullScreen = true;
                this.$video.webkitRequestFullScreen();
            } else {
                this.state.fullScreen = false;
                document.webkitCancelFullScreen();
            }
            setTimeout(this.initVideo, 200);
        },
        mouseMoveAction(e) {
            if (this.volume.moving) {
                this.volSlideMove(e);
            }
            if (this.video.moving) {
                this.videoSlideMove(e);
            }
            this.contrlHider(e);
        },
        contrlHider(e) {
            const x = getMousePosition(e, "x");
            const y = getMousePosition(e, "y");
            if (!this.player.pos) return;
            if (
                x > this.player.pos.left &&
                x < this.player.pos.left + this.player.pos.width
            ) {
                if (
                    y > this.player.pos.top + this.player.pos.height * 0.6 &&
                    y < this.player.pos.top + this.player.pos.height
                ) {
                    return this.mouseEnterVideo();
                }
            }
            return this.mouseLeaveVideo();
        },
        volSlideMove(e) {
            const x = getMousePosition(e) - this.volume.pos.start;
            if (x > 0 && x < this.volume.pos.width) {
                this.setVol(x / this.volume.pos.width);
            }
        },
        videoSlideMove(e) {
            const x = getMousePosition(e) - this.video.pos.start;
            if (x > 0 && x < this.video.pos.width) {
                this.video.pos.current = x;
                this.setVideoByTime(x / this.video.pos.width);
            }
        },
        mouseUpAction() {
            this.volume.moving = false;
            this.video.moving = false;
        },
    },
};
</script>

<style lang="less">
@import "./style.less";
</style>
